package router

import (
	"git.huoys.com/block_chain/mall/ecode"
	pb "git.huoys.com/block_chain/mall/internal/user/api"
	"git.huoys.com/block_chain/mall/internal/user/model"
	"git.huoys.com/block_chain/mall/internal/user/service"
	"git.huoys.com/block_chain/mall/pkg/app"
	"git.huoys.com/block_chain/mall/pkg/log"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type UserHandler interface {
	// 注销用户
	DelUser(ctx *gin.Context)
	// 修改帐号信息
	UpdateUser(ctx *gin.Context)
	// 绑定邀请码
	BindingInvitationCode(ctx *gin.Context)
	// 获取钱包信息
	GetWallet(ctx *gin.Context)
	// 转账
	Transaction(ctx *gin.Context)
	// 获取转账记录
	GetTransactionRecord(ctx *gin.Context)

	// 获取自己下级
	GetDescendantByUid(ctx *gin.Context)
	// 获取自己全部下级
	GetAllDescendantByUid(ctx *gin.Context)
	// 获取自己上级
	GetAncestorByUid(ctx *gin.Context)
	// 获取自己全部上级
	GetAllAncestorByUid(ctx *gin.Context)
}

type userHandler struct {
	service service.UserService
}

func NewCommentHandler(s service.UserService) UserHandler {
	return &userHandler{
		service: s,
	}
}

// 注销用户
func (c *userHandler) DelUser(ctx *gin.Context) {
	var param = pb.DelUserReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.Empty{}
	var err error
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	err = c.service.DelUser(param.GetUid())
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	response.ToResponse(resp)
	return
}

// 更新用户信息
func (c *userHandler) UpdateUser(ctx *gin.Context) {
	var param = pb.UpdateUserReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.Empty{}
	var err error
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid || param.Uid == 0 {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	err = c.service.UpdateUser(model.UpdateUserReqToUser(param))
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	response.ToResponse(resp)
	return
}

// 绑定邀请码
func (c *userHandler) BindingInvitationCode(ctx *gin.Context) {
	var param = pb.BindingInvitationCodeReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.Empty{}
	var err error
	var success bool
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	success, err = c.service.BindingInvitationCode(param.Uid, param.Code)
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	if !success {
		response.ToErrorResponse(ecode.ErrInvitationBined)
		return
	}
	response.ToResponse(resp)
	return
}

// 获取钱包信息
func (c *userHandler) GetWallet(ctx *gin.Context) {
	var param = pb.GetWalletReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.GetWalletResp{}
	var err error
	var wallet model.Wallet
	var balances string
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	// todo : 这里在考虑是否需要uid才能获取钱包信息
	if uid == 0 {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	wallet, balances, err = c.service.GetWallet(param.GetWid())
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	resp.Wallet = wallet.ToPbWallet()
	resp.Wallet.Balances = balances
	response.ToResponse(resp)
	return
}

// 转账
func (c *userHandler) Transaction(ctx *gin.Context) {
	var param = pb.TransactionReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.Empty{}
	var err error
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetFromUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	_, err = c.service.Transaction(param.GetFromUid(), param.GetToUid(), 0, param.GetAddr(), param.Price)
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	response.ToResponse(resp)
	return
}

// 获取转账记录
func (c *userHandler) GetTransactionRecord(ctx *gin.Context) {
	var param = pb.GetTransferRecordReq{}
	var response = app.NewResponse(ctx)
	//var resp = pb.GetTransferRecordResp{}
	var err error
	var record []model.OrderTransferRecord
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	record, err = c.service.GetTransactionRecord(param.GetUid())
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	for i := range record {
		if record[i].FromUID == param.GetUid() {
			record[i].Price = 0 - record[i].Price
		}
	}
	response.ToResponse(record)
	return
}

// 获取自己下级
func (c *userHandler) GetDescendantByUid(ctx *gin.Context) {
	var param = pb.GetInvitationInfoSelfReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.GetInvitationInfoSelfToUserResp{}
	var err error
	var subordinate model.User
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	subordinate, err = c.service.GetDescendantByUid(param.GetUid())
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	resp.User = subordinate.ToPbUserSimple()
	response.ToResponse(resp)
	return
}

// 获取自己全部下级
func (c *userHandler) GetAllDescendantByUid(ctx *gin.Context) {
	var param = pb.GetInvitationInfoSelfReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.GetInvitationInfoSelfToUserSResp{}
	var err error
	var subordinate []model.User
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	subordinate, err = c.service.GetAllDescendantByUid(param.GetUid())
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	resp.Users = make([]*pb.UserSimple, len(subordinate))
	for i := range subordinate {
		resp.Users[i] = subordinate[i].ToPbUserSimple()
	}
	response.ToResponse(resp)
	return
}

// 获取自己上级
func (c *userHandler) GetAncestorByUid(ctx *gin.Context) {
	var param = pb.GetInvitationInfoSelfReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.GetInvitationInfoSelfToUserResp{}
	var err error
	var superior model.User
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api GetAncestorByUid app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	superior, err = c.service.GetAncestorByUid(param.GetUid())
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	resp.User = superior.ToPbUserSimple()
	response.ToResponse(resp)
	return
}

// 获取自己全部上级
func (c *userHandler) GetAllAncestorByUid(ctx *gin.Context) {
	var param = pb.GetInvitationInfoSelfReq{}
	var response = app.NewResponse(ctx)
	var resp = pb.GetInvitationInfoSelfToUserSResp{}
	var err error
	var superior []model.User
	valid, errs := app.BindAndValid(ctx, &param)
	if !valid {
		log.GetLogger().Error("api DelUser app.BindAndValid failed",
			zap.Any("param", param),
			zap.Any("errs", errs),
		)
		response.ToErrorResponse(ecode.ParamErr)
		return
	}
	var uid uint64
	uid = app.GetUid(ctx)
	if uid == 0 || uid != param.GetUid() {
		response.ToErrorResponse(ecode.AccessDenied)
		return
	}
	superior, err = c.service.GetAllDescendantByUid(param.GetUid())
	if err != nil {
		response.ToErrorResponse(err)
		return
	}
	resp.Users = make([]*pb.UserSimple, len(superior))
	for i := range superior {
		resp.Users[i] = superior[i].ToPbUserSimple()
	}
	response.ToResponse(resp)
	return
}
